---
title: Tooltips
---

Victory supports multiple ways to show tooltips on your charts. Tooltips can be added to any Victory component, and can be customized to suit your needs. This guide will cover the basics of adding tooltips to your charts, as well as more advanced configurations.

## Basic

The simplest way to add tooltips to a chart is to use `VictoryTooltip` as a `labelComponent`. By default, the `labelComponent` will display the `label` prop of the data point it is associated with, unless you specify a custom `labels` function.

```jsx live
<VictoryChart
  domain={{ x: [0, 11], y: [-10, 10] }}
  theme={VictoryTheme.clean}
>
  <VictoryBar
    labelComponent={<VictoryTooltip />}
    data={[
      { x: 2, y: 5 },
      { x: 4, y: -6 },
      { x: 6, y: 4 },
      { x: 8, y: -5 },
      { x: 10, y: 7 },
    ]}
    labels={({ datum }) => datum.y}
  />
</VictoryChart>
```

## Styles

`VictoryTooltip` can be styled using the `style` prop. The `style` prop accepts an object with `data`, `labels`, and `flyout` keys. The `data` key styles the data point, the `labels` key styles the text of the tooltip, and the `flyout` key styles the background of the tooltip.

```jsx live
<VictoryChart
  domain={{ x: [0, 11], y: [-10, 10] }}
  theme={VictoryTheme.clean}
>
  <VictoryBar
    labelComponent={
      <VictoryTooltip
        cornerRadius={({ datum }) =>
          datum.x > 6 ? 0 : 20
        }
        pointerLength={({ datum }) =>
          datum.y > 0 ? 5 : 20
        }
        flyoutStyle={{
          stroke: ({ datum }) =>
            datum.x === 10
              ? "tomato"
              : "black",
        }}
      />
    }
    data={[
      {
        x: 2,
        y: 5,
        label: "right-side-up",
      },
      {
        x: 4,
        y: -6,
        label: "upside-down",
      },
      { x: 6, y: 4, label: "tiny" },
      {
        x: 8,
        y: -5,
        label: "or a little \n BIGGER",
      },
      {
        x: 10,
        y: 7,
        label: "automatically",
      },
    ]}
    style={{
      data: { width: 20 },
    }}
  />
</VictoryChart>
```

## Events

`VictoryTooltip` automatically attaches events to data components. When events of the same type are specified for data components, it is necessary to reconcile events so that tooltips still work. For web, the default tooltip events are:

```jsx
static defaultEvents = [{
  target: "data",
  eventHandlers: {
    onMouseOver: () => ({
      target: "labels",
      mutation: () => ({ active: true })
    }),
    onMouseOut: () => ({
      target: "labels",
      mutation: () => ({ active: undefined })
    }),
    onFocus: () => ({
      target: "labels",
      mutation: () => ({ active: true })
    }),
    onBlur: () => ({
      target: "labels",
      mutation: () => ({ active: undefined })
    })
  }
}];
```

:::warning
When other `onMouseOver` and `onMouseOut` events are specified for data, the event returns described above must be added to the events for tooltips to continue to work properly.
:::

```jsx live
<VictoryChart
  domain={{ x: [0, 11], y: [-10, 10] }}
  theme={VictoryTheme.clean}
>
  <VictoryBar
    labelComponent={<VictoryTooltip />}
    data={[
      { x: 2, y: 5, label: "A" },
      { x: 4, y: -6, label: "B" },
      { x: 6, y: 4, label: "C" },
      { x: 8, y: -5, label: "D" },
      { x: 10, y: 7, label: "E" },
    ]}
    style={{
      data: { width: 20 },
    }}
    events={[
      {
        target: "data",
        eventHandlers: {
          onMouseOver: () => {
            return [
              {
                target: "data",
                mutation: () => ({
                  style: {
                    fill: "gold",
                    width: 30,
                  },
                }),
              },
              {
                target: "labels",
                mutation: () => ({
                  active: true,
                }),
              },
            ];
          },
          onMouseOut: () => {
            return [
              {
                target: "data",
                mutation: () => {},
              },
              {
                target: "labels",
                mutation: () => ({
                  active: false,
                }),
              },
            ];
          },
        },
      },
    ]}
  />
</VictoryChart>
```

---

## Voronoi

Use `VictoryVoronoiContainer` to associate a mouse position with the data point(s)
closest to it. When this container is added to a chart, changes in mouse position will add the `active`
prop to data and label components closest to the current mouse position. The closeness of data
points to a given position is determined by calculating a voronoi diagram based on the data of
every child `VictoryVoronoiContainer` renders. This container is useful for adding hover interactions,
like tooltips, to small data points, or charts with dense or overlapping data.

See the [full API here](/docs/api/victory-voronoi-container).

### Basic

`VictoryVoronoiContainer` may be used with any Victory component that works with an x-y coordinate
system, and should be added as the `containerComponent` of the top-level component.
However, the component that uses it must be standalone
(`standalone={true}`), which is the default for all top-level Victory components.

```jsx live
<VictoryChart
  domain={{ x: [0, 5], y: [-5, 5] }}
  containerComponent={
    <VictoryVoronoiContainer />
  }
  theme={VictoryTheme.clean}
>
  <VictoryScatter
    size={({ active }) =>
      active ? 5 : 3
    }
    labels={({ datum }) => datum.y}
    labelComponent={<VictoryTooltip />}
    data={[
      { x: 1, y: -4 },
      { x: 2, y: 4 },
      { x: 3, y: 2 },
      { x: 4, y: 1 },
    ]}
  />
  <VictoryScatter
    size={(datum, active) =>
      active ? 5 : 3
    }
    labels={({ datum }) => datum.y}
    labelComponent={<VictoryTooltip />}
    data={[
      { x: 1, y: -3 },
      { x: 2, y: 3 },
      { x: 3, y: 3 },
      { x: 4, y: 0 },
    ]}
  />
  <VictoryScatter
    data={[
      { x: 1, y: 4 },
      { x: 2, y: -4 },
      { x: 3, y: -2 },
      { x: 4, y: -3 },
    ]}
    labels={({ datum }) => datum.y}
    labelComponent={<VictoryTooltip />}
    size={({ active }) =>
      active ? 5 : 3
    }
  />
</VictoryChart>
```

### Follow Tooltips

When using `VictoryVoronoiContainer` with `VictoryTooltip`, you can add tooltips to your chart that follow the mouse position.

```jsx live
<VictoryChart
  theme={VictoryTheme.clean}
  domain={{ y: [0, 1] }}
  containerComponent={
    <VictoryVoronoiContainer
      labels={({ datum }) =>
        `Data ${datum.y}`
      }
      mouseFollowTooltips
      labelComponent={
        <VictoryTooltip
          constrainToVisibleArea
        />
      }
    />
  }
>
  <VictoryScatter
    data={[
      { x: 1, y: 0 },
      { x: 2, y: 0 },
      { x: 3, y: 0 },
      { x: 4, y: 0 },
      { x: 5, y: 0 },
      { x: 6, y: 0 },
      { x: 7, y: 0 },
    ]}
    style={{
      data: {
        fill: VictoryTheme.clean.palette
          ?.colors.blue,
      },
    }}
    size={({ active }) =>
      active ? 8 : 3
    }
  />
  <VictoryScatter
    data={[
      { x: 1, y: 0 },
      { x: 2, y: 0 },
      { x: 3, y: 1 },
      { x: 4, y: 0 },
      { x: 5, y: 0 },
      { x: 6, y: 0 },
      { x: 7, y: 0 },
    ]}
    style={{
      data: {
        fill: VictoryTheme.clean.palette
          ?.colors.red,
      },
    }}
    size={({ active }) =>
      active ? 5 : 3
    }
  />
</VictoryChart>
```

### Active Points

`VictoryVoronoiContainer` adds the `active` prop to any data point closest to the current mouse position. This prop can be used to style the active data point differently from the rest.

```jsx live
<VictoryChart
  domainPadding={{ y: 10 }}
  containerComponent={
    <VictoryVoronoiContainer
      labels={({ datum }) =>
        `${_.round(datum.x, 2)}, ${_.round(
          datum.y,
          2,
        )}`
      }
    />
  }
  theme={VictoryTheme.clean}
>
  <VictoryScatter
    y={(datum) =>
      Math.sin(2 * Math.PI * datum.x)
    }
    style={{
      data: {
        fill: ({ active }) =>
          active
            ? VictoryTheme.clean.palette
                ?.colors.red
            : VictoryTheme.clean.palette
                ?.colors.blue,
      },
    }}
  />
</VictoryChart>
```

### Multipoint Labels

`VictoryVoronoiContainer` can also be used to create multi-point labels when the `labels` prop is
provided. In the example below the `voronoiDimension` prop indicates that the voronoi diagram
will only be specific to the x dimension. For a given mouse position, all data matching the
associated x value will be activated regardless of y value. In the following example, this leads to
several tooltips being active at the same time. Provide a `labels` and (optionally) a
`labelComponent` prop to configure multi-point labels.

```jsx live
<VictoryChart
  domainPadding={{ y: 10 }}
  containerComponent={
    <VictoryVoronoiContainer
      voronoiDimension="x"
      labels={({ datum }) =>
        `y: ${datum.y}`
      }
      labelComponent={
        <VictoryTooltip
          cornerRadius={0}
          flyoutStyle={{
            fill: "white",
          }}
        />
      }
    />
  }
  theme={VictoryTheme.clean}
>
  <VictoryLine
    data={[
      { x: 1, y: 5, l: "one" },
      {
        x: 1.5,
        y: 5,
        l: "one point five",
      },
      { x: 2, y: 4, l: "two" },
      { x: 3, y: -2, l: "three" },
    ]}
    style={{
      data: {
        stroke: "tomato",
        strokeWidth: ({ active }) =>
          active ? 4 : 2,
      },
      labels: { fill: "tomato" },
    }}
  />

  <VictoryLine
    data={[
      { x: 1, y: -3, l: "red" },
      { x: 2, y: 5, l: "green" },
      { x: 3, y: 3, l: "blue" },
    ]}
    style={{
      data: {
        stroke: "blue",
        strokeWidth: ({ active }) =>
          active ? 4 : 2,
      },
      labels: { fill: "blue" },
    }}
  />

  <VictoryLine
    data={[
      { x: 1, y: 5, l: "cat" },
      { x: 2, y: -4, l: "dog" },
      { x: 3, y: -2, l: "bird" },
    ]}
    style={{
      data: {
        stroke: "black",
        strokeWidth: ({ active }) =>
          active ? 4 : 2,
      },
      labels: { fill: "black" },
    }}
  />
</VictoryChart>
```

---

## Cursor

Use `VictoryCursorContainer` to add a cursor to a chart to inspect coordinates.
The cursor can either be a 2-dimensional crosshair, or a 1-dimensional line.
The cursor moves with the mouse (or on touch on mobile devices) along the visible domain of the chart.
The cursor can also display a label for the active coordinates using the `cursorLabel` prop.

See the [full API here](/docs/api/victory-cursor-container).

### Line Charts

Using the `VictoryCursorContainer` component, you can add a 2D cursor to a line chart.

```jsx live
<VictoryChart
  containerComponent={
    <VictoryCursorContainer
      cursorLabel={({ datum }) =>
        `${_.round(datum.x, 2)}, ${_.round(
          datum.y,
          2,
        )}`
      }
    />
  }
  theme={VictoryTheme.clean}
>
  <VictoryScatter
    y={(d) => d.x * d.x}
  />
</VictoryChart>
```

### Dimension Limits

You can also use the `cursorDimension` prop to create a 1D cursor. This is useful for line charts where you only want to inspect one dimension. Note you can also set a `defaultCursorValue` to set the initial position of the cursor.

```jsx live
<VictoryChart
  containerComponent={
    <VictoryCursorContainer
      cursorLabel={({ datum }) =>
        `${_.round(datum.x, 2)}, ${_.round(
          datum.y,
          2,
        )}`
      }
      cursorDimension="x"
      defaultCursorValue={0.3}
    />
  }
  theme={VictoryTheme.clean}
>
  <VictoryScatter
    y={(d) => d.x * d.x}
  />
</VictoryChart>
```

### Bar Charts

You can also use the `VictoryCursorContainer` component with bar charts.

```jsx live
<VictoryChart
  horizontal
  theme={VictoryTheme.clean}
  domainPadding={{ x: 15 }}
  containerComponent={
    <VictoryCursorContainer
      cursorLabel={({ datum }) =>
        _.round(datum.x, 2)
      }
      cursorDimension="y"
      defaultCursorValue={3}
    />
  }
>
  <VictoryGroup offset={10}>
    <VictoryBar
      data={[
        { x: 1, y: 5, l: "one" },
        { x: 2, y: 4, l: "two" },
        { x: 3, y: -2, l: "three" },
      ]}
    />

    <VictoryBar
      data={[
        { x: 1, y: -3, l: "red" },
        { x: 2, y: 5, l: "green" },
        { x: 3, y: 3, l: "blue" },
      ]}
    />

    <VictoryBar
      data={[
        { x: 1, y: 5, l: "cat" },
        { x: 2, y: -4, l: "dog" },
        { x: 3, y: -2, l: "bird" },
      ]}
    />
  </VictoryGroup>
</VictoryChart>
```

### Scatter Charts

You can also use the `VictoryCursorContainer` component with scatter charts. Note how we can apply the container directly to the `VictoryScatter` component.

```jsx live
<VictoryScatter
  theme={VictoryTheme.clean}
  style={{
    data: {
      fill: ({ active }) =>
        active
          ? VictoryTheme.clean.palette
              ?.colors.teal || "teal"
          : VictoryTheme.clean.palette
              ?.colors.purple ||
            "purple",
    },
  }}
  containerComponent={
    <VictoryCursorContainer
      theme={VictoryTheme.clean}
      cursorLabel={({ datum }) =>
        _.round(datum.x, 2)
      }
      defaultCursorValue={1}
    />
  }
  data={[
    { x: -3, y: 2 },
    { x: 0, y: -2 },
    { x: -8, y: 1 },
    { x: -2, y: -3 },
    { x: 7, y: 5 },
    { x: -8, y: 6 },
    { x: -1, y: 3 },
    { x: -4, y: -5 },
    { x: -6, y: -5 },
  ]}
/>
```

### Events

You can also use the `onCursorChange` prop to listen to cursor changes and inspect the values.

```jsx live noInline
function App() {
  const [cursorValue, setCursorValue] =
    React.useState(null);

  function onCursorChange(value) {
    setCursorValue(value);
  }

  return (
    <VictoryChart
      theme={VictoryTheme.clean}
      containerComponent={
        <VictoryCursorContainer
          cursorLabel={({ datum }) =>
            _.round(datum.x, 2)
          }
          cursorLabelOffset={15}
          onCursorChange={
            onCursorChange
          }
        />
      }
    >
      <VictoryGroup>
        <VictoryScatter
          style={{
            data: {
              fill: VictoryTheme.clean
                .palette?.colors.red,
            },
          }}
          data={[
            { x: 1, y: -5 },
            { x: 2, y: 4 },
            { x: 3, y: 2 },
            { x: 4, y: 0 },
            { x: 5, y: 1 },
            { x: 6, y: -3 },
            { x: 7, y: 3 },
          ]}
        />
        <VictoryScatter
          style={{
            data: {
              fill: VictoryTheme.clean
                .palette?.colors.yellow,
            },
          }}
          data={[
            { x: 1, y: -3 },
            { x: 2, y: 5 },
            { x: 3, y: 3 },
            { x: 4, y: 0 },
            { x: 5, y: -2 },
            { x: 6, y: -2 },
            { x: 7, y: 5 },
          ]}
        />
        <VictoryScatter
          data={[
            { x: 1, y: 5 },
            { x: 2, y: -4 },
            { x: 3, y: -2 },
            { x: 4, y: -3 },
            { x: 5, y: -1 },
            { x: 6, y: 3 },
            { x: 7, y: -3 },
          ]}
        />
      </VictoryGroup>
      {cursorValue && (
        <VictoryLabel
          x={20}
          y={20}
          text={JSON.stringify(
            cursorValue,
          )}
        />
      )}
    </VictoryChart>
  );
}

render(<App />);
```

---

## Custom Components

`VictoryTooltip` is composed of [`VictoryLabel`](/docs/api/victory-label) and the primitive [`Flyout`](/docs/api/victory-primitives#flyout) component. Both of these components are highly configurable, but may also be replaced if necessary.

### Custom Flyout

An example of replacing the default `Flyout` component with a custom component.

```jsx live noInline
const colors =
  VictoryTheme.clean.palette.cool;

function CustomFlyout(props) {
  const { x, y, orientation } = props;
  const newY =
    orientation === "bottom"
      ? y - 35
      : y + 35;
  return (
    <g>
      <circle
        cx={x}
        cy={newY}
        r="20"
        stroke={colors[0]}
        fill="none"
      />
      <circle
        cx={x}
        cy={newY}
        r="25"
        stroke={colors[1]}
        fill="none"
      />
      <circle
        cx={x}
        cy={newY}
        r="30"
        stroke={colors[2]}
        fill="none"
      />
    </g>
  );
}

function App() {
  return (
    <VictoryChart
      domain={{
        x: [0, 11],
        y: [-10, 10],
      }}
      theme={VictoryTheme.clean}
    >
      <VictoryBar
        labelComponent={
          <VictoryTooltip
            flyoutComponent={
              <CustomFlyout />
            }
          />
        }
        data={[
          { x: 2, y: 5, label: "A" },
          { x: 4, y: -6, label: "B" },
          { x: 6, y: 4, label: "C" },
          { x: 8, y: -5, label: "D" },
          { x: 10, y: 7, label: "E" },
        ]}
        style={{
          data: { width: 20 },
        }}
      />
    </VictoryChart>
  );
}
render(<App />);
```

### Custom Label

An example of using custom labels with a donut chart.

```jsx live noInline
function CustomLabel(props) {
  return (
    <g>
      <VictoryLabel {...props} />
      <VictoryTooltip
        {...props}
        x={226}
        y={197}
        orientation="top"
        pointerLength={0}
        cornerRadius={50}
        flyoutWidth={100}
        flyoutHeight={100}
        flyoutStyle={{
          fill: "#bdbdbd",
        }}
      />
    </g>
  );
}

CustomLabel.defaultEvents =
  VictoryTooltip.defaultEvents;

function App() {
  return (
    <VictoryPie
      theme={VictoryTheme.clean}
      style={{
        labels: { fill: "white" },
      }}
      innerRadius={80}
      labelRadius={100}
      radius={140}
      labelComponent={<CustomLabel />}
      data={[
        { x: 1, y: 5, label: "Dogs" },
        { x: 2, y: 4, label: "Cats" },
        {
          x: 3,
          y: 2,
          label: "Rabbits",
        },
        { x: 4, y: 3, label: "Birds" },
        { x: 5, y: 1, label: "Snakes" },
      ]}
    />
  );
}

render(<App />);
```

### Custom Wrapping

The events that control `VictoryTooltip` are stored on the static `defaultEvents` property. Wrapped instances of `VictoryTooltip` will need to replicate or hoist this property in order to add automatic events to the components that use them.

```jsx live noInline
function CustomTooltip(props) {
  const { x, y } = props;
  const rotation = `rotate(45 ${x} ${y})`;
  return (
    <g transform={rotation}>
      <VictoryTooltip
        {...props}
        renderInPortal={false}
      />
    </g>
  );
}
CustomTooltip.defaultEvents =
  VictoryTooltip.defaultEvents;

function App() {
  return (
    <VictoryChart
      domain={{
        x: [0, 11],
        y: [-10, 10],
      }}
      theme={VictoryTheme.clean}
    >
      <VictoryBar
        labelComponent={
          <CustomTooltip />
        }
        data={[
          { x: 2, y: 5, label: "A" },
          { x: 4, y: -6, label: "B" },
          { x: 6, y: 4, label: "C" },
          { x: 8, y: -5, label: "D" },
          { x: 10, y: 7, label: "E" },
        ]}
      />
    </VictoryChart>
  );
}
render(<App />);
```

## Victory Native

In Victory Native tooltips are much more reliable when using `VictoryVoronoiContainer`. Using `VictoryVoronoiContainer` registers all touch events on the container itself, which mitigates interference with other chart elements, which can be a problem on some platforms. Showing the closest data point with `VictoryVoronoiContainer` also increases the tap targets for the tooltip, which can otherwise be quite small. Set `VictoryVoronoiContainer` as the `containerComponent` prop on the outermost Victory component.

```jsx
<VictoryChart
  containerComponent={
    <VictoryVoronoiContainer />
  }
>
  <VictoryScatter
    labelComponent={<VictoryTooltip />}
    labels={({ datum }) => datum.y}
    style={{
      data: {
        fill: ({ datum }) => datum.fill,
      },
    }}
    data={[
      { x: 1, y: 3 },
      { x: 3, y: 5 },
    ]}
  />
</VictoryChart>
```
